package com.orderplus.opshop.synces.service.elasticsearch.impl;

import com.orderplus.opshop.common.util.ValueUtil;
import com.orderplus.opshop.core.data.request.RequestParam;
import com.orderplus.opshop.core.exception.CheckedException;
import com.orderplus.opshop.synces.service.elasticsearch.data.Condition;
import com.orderplus.opshop.synces.service.elasticsearch.data.QueryParamData;
import com.orderplus.opshop.synces.service.elasticsearch.data.QueryResultData;
import com.orderplus.opshop.synces.service.elasticsearch.data.Type;
import com.orderplus.opshop.synces.service.elasticsearch.service.impl.base.AggsQuery;
import com.orderplus.opshop.synces.service.elasticsearch.service.impl.base.ListQuery;
import com.orderplus.opshop.synces.template.EsPageTemplate;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.rest.RestStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Service
public class OpSearchService extends EsPageTemplate {
	@Autowired
	private ListQuery listQuery;

	@Autowired
	private AggsQuery aggsQuery;

	@Override
	protected QueryResultData.ListQueryResultData callInner(RequestParam<QueryParamData> request) throws Exception {
		QueryResultData.ListQueryResultData resultData = null;
		try {
			QueryParamData queryParamData = request.getRequestBody();

			resultData = listQuery.query(queryParamData);
		} catch (ElasticsearchException e) {
			//如果查找不到记录
			if (e.status() == RestStatus.NOT_FOUND) {
				return null;
			} else {
				throw e;
			}
		}
		return resultData;
	}

	public QueryParamData setCondition(String indices, String[] key, Object[] value) {
		QueryParamData queryParamData = new QueryParamData();

		queryParamData.setIndices(indices);

		Condition[] conditions = new Condition[key.length];

		for (int i = 0; i < key.length; i++) {
			Condition.CommonCondition commonCondition = new Condition.CommonCondition(key[i], Type.FieldType.TERM, Type.BoolType.MUST, value[i]);
			conditions[i] = commonCondition;
		}
		queryParamData.setConditions(conditions);

		return queryParamData;
	}

	public QueryResultData.AggsQueryResultData queryAggsData(String indices, String[] key, Object[] value) throws IOException {
		QueryParamData queryParamData = new QueryParamData();

		queryParamData.setIndices(indices);

		Condition[] conditions = new Condition[key.length];

		for (int i = 0; i < key.length; i++) {
			Condition.AggCondition condition = new Condition.AggCondition(key[i] + ".keyword", Type.AggType.TERMS);

			conditions[i] = condition;
		}

		queryParamData.setConditions(conditions);

		QueryResultData.AggsQueryResultData aggsQueryResultData = aggsQuery.query(queryParamData);

		return aggsQueryResultData;
	}

	public int queryTotal(String indices, String[] key, Object[] value) throws IOException {
		QueryResultData.AggsQueryResultData aggsQueryResultData = queryAggsData(indices, key, value);

		List<Map<Object, Object>> statisMapList = aggsQueryResultData.getStatisMapList();

		int total = 0;

		for (int i = 0; i < value.length; i++) {
			String keyTemp = new StringBuffer(key[i]).append(".keyword").toString();
			for (Map<Object, Object> map : statisMapList) {
				for (Map.Entry<Object, Object> entry : map.entrySet()) {
					Map<String, Object> keyMap = (Map<String, Object>) entry.getKey();
					String queryKey = ValueUtil.toStr(keyMap.get("key"));
					int queryValue = ValueUtil.toInt(keyMap.get("value"));
					String field = ValueUtil.toStr(keyMap.get("field"));

					if (keyTemp.equals(field) && value[i].equals(queryKey)) {
						total += queryValue;
						break;
					}
				}
			}
		}

		return total;
	}

	public RequestParam<QueryParamData> setDefaultParam(String indices, String[] key, Object[] value, int pageIndex, int pageSize) throws IOException {
		if (key.length != value.length) {
			throw new CheckedException("key length not equals value length");
		}

		RequestParam<QueryParamData> request = new RequestParam<>();

		QueryParamData queryParamData = setCondition(indices, key, value);

		queryParamData.setPageIndex(pageIndex);
		queryParamData.setPageSize(pageSize);

		request.setRequestBody(queryParamData);

		return request;
	}

}
